/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 *
 */

import { getAlignTarget } from '@ohos/hvigor/src/base/util/task-util';
import os from 'os';

import { DefaultTargetConst } from '../const/common-const.js';
import { OhosPluginId } from '../plugin/common/ohos-plugin-id.js';
import { HspPlugin } from '../plugin/hsp-plugin.js';
import { ModuleTargetData } from '../tasks/data/hap-task-target-data.js';
import { checkHasTargetApplyProduct } from '../tasks/service/module-task-service.js';
import { TargetTaskService } from '../tasks/service/target-task-service.js';

import { OhosLogger } from './log/ohos-logger';
import { TargetUtils } from './target-utils.js';

export class HspTargetUtils {
  private static _log: OhosLogger = OhosLogger.getLogger('HspTargetUtils');

  /**
   * 获取依赖的hsp模块的可用target
   *
   * @param targetService
   */
  static calDepHspTargets(targetService: TargetTaskService) {
    const depHspTargets = new Map<string, ModuleTargetData>();
    const targetData: ModuleTargetData = targetService.getTargetData();
    const service = targetService.getModuleService();
    const moduleModel = service.getModuleModel();
    const moduleName: string = moduleModel.getName();
    const curTarget = getAlignTarget() ?? targetData.getTargetName();
    const curProduct = targetData.getProduct().name;

    service.getHspModuleDependencyNames().forEach((hspName) => {
      const hspModule = moduleModel.getModule().findModuleByName(hspName);
      if (!hspModule) {
        this._log.printErrorExit('HSP_NOT_FOUND', [hspName], [[hspName]]);
      }
      const printError = () => {
        const detail1 = `Module '${moduleName}@${curTarget}' depends on shared library module '${hspName}', `;
        const detail2 =
          `but neither target '${curTarget}' nor target '${DefaultTargetConst.DEFAULT_TARGET}' of ` +
          `module '${hspName}' is applied to current product '${curProduct}'.${os.EOL}`;
        const detail3 = `but target '${curTarget}' of ` + `module '${hspName}' is not applied to current product '${curProduct}'.${os.EOL}`;
        const detail4 = `\tSolution: Apply one of these targets of module '${hspName}' to product '${curProduct}': ` + `${os.EOL}\t\t- default`;
        const detail5 = `${os.EOL}\t\t- ${curTarget}`;
        const detail = curTarget === DefaultTargetConst.DEFAULT_TARGET ? `${detail1}${detail3}${detail4}` : `${detail1}${detail2}${detail4}${detail5}`;
        this._log.printErrorExit('HSP_TARGET_NOT_MATCH', [targetData.getTargetName(), hspName, detail], [[hspName, moduleName]]);
      };
      const hspPlugin = hspModule!.getPluginById(OhosPluginId.OHOS_HSP_PLUGIN) as HspPlugin;
      const hspTargets = hspPlugin.getNeedExecTargetServiceList();
      if (0 === hspTargets.length) {
        printError();
      }
      // 对target优先级进行整理
      const tryTargets = TargetUtils.pushTryTargets({
        projectModel: targetService.getModuleService().getProjectModel(),
        moduleName: hspName,
        superTargetName: targetData.getTargetName(),
      });
      const tryTargetDatas: ModuleTargetData[] = [];
      // 尝试寻找当前target或default target
      for (const target of tryTargets) {
        // find方法返回首个结果，但正常情况下应该没有重复target
        const hspTargetService = hspTargets.find(
          (targetData) =>
            targetData.getTargetData().getTargetName() === target &&
            checkHasTargetApplyProduct(targetData.getTargetData().getModuleModel(), target, curProduct),
        );
        if (hspTargetService !== undefined) {
          tryTargetDatas.push(hspTargetService.getTargetData());
          break;
        }
      }

      // 如果target里没有收获，就从对应模块apply to当前product的target里面选择一个
      if (tryTargetDatas.length === 0 && hspTargets.length > 0) {
        const possibleTargetData = hspTargets.find((targetData) =>
          checkHasTargetApplyProduct(targetData.getModuleService().getModuleModel(), targetData.getTargetData().getTargetName(), curProduct),
        );
        if (possibleTargetData) {
          tryTargetDatas.push(possibleTargetData.getTargetData());
        } else {
          printError();
        }
      }
      tryTargetDatas.forEach((targetData) => depHspTargets.set(hspName, targetData));
    });
    return depHspTargets;
  }
}
